package cn.shutdown.demo.jvm;

/**
 * 本类测试栈上分配，逃逸分析，局部变量范围未超出函数体可能会被分配到栈而不是堆
 *
 * 执行方法要加以下jvm参数
 * -server -Xmx10m -Xms5m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-UseTLAB -XX:+EliminateAllocations
 * 说明：
 * -server server模式下才会启用逃逸分析
 * -Xmx10m 指定堆空间最大内存为10M
 * -XX:+DoEscapeAnalysis 启用逃逸分析
 * -XX:+PrintGC 打印GC日志
 * -XX:-UseTLAB 关闭TLAB Thread Local Allocation Buffer 线程本地分配缓存
 * -XX:+EliminateAllocations 开启标量替换（默认是打开的），允许将对象打散分配到栈上，如对象拥有id和name
 *      这两人个变量将被视为两个独立的局部变量进行分配
 * 执行结果
 * [GC (Allocation Failure)  1023K->565K(5632K), 0.0012699 secs]
 * [GC (Allocation Failure)  1589K->613K(6656K), 0.0015624 secs]
 * 9
 *  GC (Allocation Failure) ： 发生了一次垃圾回收，若前面有Full则表明是Full GC，没有Full的修饰表明这是一次Minor GC
 *  。注意它不表示只GC新生代，括号里的内容是gc发生的原因，这里的Allocation Failure的原因是年轻代中没有足够区域能够存放需要分配的数据而失败，。
 *  参考：https://blog.csdn.net/topdeveloperr/article/details/88874957
 *
 *
 * @author jiangwujie
 * @date 2021/5/19
 */
public class OnStackTest {

    public static class User {
        public int id = 0;
        public String name = "";
    }

    public static void alloc() {
        User user = new User();
        user.id = 5;
        user.name = "dmn";
    }

    public static void main(String[] args) throws InterruptedException {
        long a = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            alloc();
        }
        long b = System.currentTimeMillis();
        System.out.println(b - a);

//        List<User> userList = new ArrayList<User>();
//        for (int i = 0; i < 200000000; i++) {
//            User user = new User();
//            user.id = 5;
//            user.name = "dmn";
//            userList.add(user);
//            System.out.println(i);
//        }
    }
}
